/**
 * STONE-CORE LIB
 * Based on Lazuli Api and Lazuli
 * @license MIT
 * @author FangLimao
 */
import {
  world,
  GameMode,
  EquipmentSlot,
  Player,
  ItemComponentTypes,
  ItemDurabilityComponent,
} from "@minecraft/server";

const neutralEffectsId = ["bad_omen", "trial_omen", "raid_omen"];

const negativeEffectsId = [
  "slowness",
  "mining_fatigue",
  "instant_damage",
  "nausea",
  "blindness",
  "hunger",
  "weakness",
  "poison",
  "wither",
  "fatal_poison",
  "levitation",
  "darkness",
  "wind_charged",
  "weaving",
  "oozing",
  "infested",
];

const positiveEffectsId = [
  "speed",
  "haste",
  "strength",
  "instant_health",
  "regeneration",
  "jump_boost",
  "invisibility",
  "water_breathing",
  "health_boost",
  "night_vision",
  "saturation",
  "absorption",
  "village_hero",
  "conduit_power",
  "slow_falling",
];

let shovelConvertBlockIds = [
  "grass_block",
  "dirt",
  "coarse_dirt",
  "mycelium",
  "podzol",
  "dirt_with_roots",
];

let axeConvertBlockIds = [
  "oak_wood",
  "spruce_wood",
  "birch_wood",
  "jungle_wood",
  "acacia_wood",
  "dark_oak_wood",
  "mangrove_wood",
  "cherry_wood",
  "crimson_hyphae",
  "warped_hyphae",
  "oak_log",
  "spruce_log",
  "birch_log",
  "jungle_log",
  "acacia_log",
  "dark_oak_log",
  "mangrove_log",
  "cherry_log",
  "crimson_stem",
  "warped_stem",
  "bamboo_block",
];

export function getEquipmentItem(entity, slot = EquipmentSlot.Mainhand) {
  return entity?.getComponent("minecraft:equippable")?.getEquipment(slot);
}

export function consumeDurability(item, value, entity) {
  const durability = item.getComponent(ItemComponentTypes.Durability);
  if (
    durability === undefined ||
    !(durability instanceof ItemDurabilityComponent)
  )
    return item;
  if (durability.damage + value >= durability.maxDurability) {
    if (entity instanceof Player) {
      entity.playSound("random.break");
    }
    return undefined;
  } else {
    durability.damage += value;
    return item;
  }
}

export function clearEffect(entity, effectType) {
  switch (effectType) {
    case "all":
      positiveEffectsId.forEach((effect) => {
        entity.removeEffect(effect);
      });
      negativeEffectsId.forEach((effect) => {
        entity.removeEffect(effect);
      });
      break;
    case "bad":
      negativeEffectsId.forEach((effect) => {
        entity.removeEffect(effect);
      });
      break;
    case "good":
      positiveEffectsId.forEach((effect) => {
        entity.removeEffect(effect);
      });
      break;
    case "nutral":
      neutralEffectsId.forEach((effect) => {
        entity.removeEffect(effect);
      });
      break;
    default:
      entity.removeEffect(effectType);
      break;
  }
}

/**
 * Define a tool tag.
 */
export class WeaponTag {
  /**
   * The weapon tag.
   */
  tag;
  constructor(tag) {
    tag = this.tag;
    this.listeningDurability();
  }
  /**
   * Automatically consume durability for the tools.
   */
  listeningDurability() {
    
  }
}

/**
 * Define a tool tag.
 */
export class ToolTag {
  /**
   * The tool tag.
   */
  tag;
  constructor(tag) {
    tag = this.tag;
    this.listeningDurability();
  }
  /**
   * Automatically consume durability for the tools.
   */
  listeningDurability() {
    world.afterEvents.playerBreakBlock.subscribe((event) => {
      const [PLAYER, ITEM] = [event.player, getEquipmentItem(event.player)];
      if (
        PLAYER.getGameMode() === GameMode.survival ||
        PLAYER.getGameMode() === GameMode.adventure
      ) {
        if (ITEM?.hasTag(this.tag)) {
          const NEW_ITEM = consumeDurability(ITEM, 1, PLAYER);
          PLAYER?.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
        }
      }
    });
    world.afterEvents.entityHitEntity.subscribe((event) => {
      const [ENTITY, ITEM] = [
        event.damagingEntity,
        getEquipmentItem(event.damagingEntity),
      ];
      if (ENTITY instanceof Player) {
        if (
          ENTITY.getGameMode() === GameMode.survival ||
          ENTITY.getGameMode() === GameMode.adventure
        ) {
          if (ITEM?.hasTag(this.tag)) {
            const NEW_ITEM = consumeDurability(ITEM, 2, ENTITY);
            ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
              EquipmentSlot.Mainhand,
              NEW_ITEM
            );
          }
        }
      } else if (ITEM?.hasTag(this.tag)) {
        const NEW_ITEM = consumeDurability(ITEM, 2, ENTITY);
        ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
          EquipmentSlot.Mainhand,
          NEW_ITEM
        );
      }
    });
  }
  /**
   * Consume durability when the tool use on dirts.
   */
  listeningShovelDurability() {
    world.afterEvents.itemUseOn.subscribe((event) => {
      const [ITEM, BLOCK, PLAYER] = [
        event.itemStack,
        event.block,
        event.source,
      ];
      if (ITEM.hasTag(this.tag)) {
        /**
         * 锹压地的事件
         */
        if (shovelConvertBlockIds.includes(BLOCK.typeId)) {
          const NEW_ITEM = consumeDurability(ITEM, 1, PLAYER);
          PLAYER.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
          PLAYER.playSound("step.grass");
        }
      }
    });
  }
  /**
   * Consume durability when the tool use on logs.
   */
  listeningAxeDurability() {
    world.afterEvents.itemUseOn.subscribe((event) => {
      const [ITEM, BLOCK, PLAYER] = [
        event.itemStack,
        event.block,
        event.source,
      ];
      if (ITEM.hasTag(this.tag)) {
        const NEW_ITEM = consumeDurability(ITEM, 1, PLAYER);
        /**
         * 斧剥皮的事件
         */
        if (axeConvertBlockIds.includes(BLOCK.typeId)) {
          PLAYER.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
          PLAYER.playSound("use.wood");
        }
      }
    });
  }
}
